home *** CD-ROM | disk | FTP | other *** search
Text File | 2007-10-18 | 66.9 KB | 1,990 lines |
- // vim: ts=2 sw=2 expandtab cindent
- //
- // BEGIN FLOCK GPL
- //
- // Copyright Flock Inc. 2005-2007
- // http://flock.com
- //
- // This file may be used under the terms of of the
- // GNU General Public License Version 2 or later (the "GPL"),
- // http://www.gnu.org/licenses/gpl.html
- //
- // Software distributed under the License is distributed on an "AS IS" basis,
- // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- // for the specific language governing rights and limitations under the
- // License.
- //
- // END FLOCK GPL
-
- // Developer ID = 1aiV9CsTs3o
- // Developer Secret = flock_is_open_source
-
- const ENABLE_DEBUG = true; // switch to turn off slow debug code for production
- function DEBUG(x) { if (ENABLE_DEBUG) debug("flockYouTubeService: "+x+"\n"); }
-
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Cr = Components.results;
-
- Components.utils.import("resource://gre/modules/JSON.jsm");
- Components.utils.import("resource:///modules/FlockScheduler.jsm");
-
- const YT_DEVID = "1aiV9CsTs3o";
- const YT_DEVSECRET = "flock_is_open_source";
- const YOUTUBE_CID = Components.ID('{DCB6A01E-7D4A-4C30-AB3D-9CC98C02F617}');
- const YOUTUBE_CONTRACTID = '@flock.com/?photo-api-youtube;1';
- const YOUTUBE_FAVICON = "http://www.youtube.com/favicon.ico";
- const YOUTUBE_TITLE = "YouTube Web Service";
- const SERVICE_ENABLED_PREF = "flock.service.youtube.enabled";
- const CATEGORY_COMPONENT_NAME = "YouTube JS Component"
- const CATEGORY_ENTRY_NAME = "youtube"
- const FRIENDS_AVATAR_TIMEOUT = 5000; // in milliseconds
- const FRIENDS_ACTIVITY_TIMEOUT = 500; // in milliseconds
-
- const FLOCK_PHOTOPERSON_CONTRACTID = '@flock.com/photo-person;1';
-
- const PROPERTY_BAG_CONTRACTID = "@mozilla.org/hash-property-bag;1";
- const XHR_CONTRACTID = "@mozilla.org/xmlextras/xmlhttprequest;1";
- const FLOCK_RDDS_CONTRACTID = "@flock.com/rich-dnd-service;1";
-
- const OBS_TOPIC_XPCOMSHUTDOWN = "xpcom-shutdown";
- const YOUTUBE_IDENTITY_URN_PREFIX = "urn:flock:identity:youtube:";
- const PEOPLE_PROPERTIES = "chrome://flock/locale/people/people.properties";
- const YOUTUBE_STRING_BUNDLE = "chrome://flock/locale/services/youtube.properties";
-
- // From nsIXMLHttpRequest.idl
- // 4: COMPLETED Finished with all operations.
- const XMLHTTPREQUEST_READYSTATE_COMPLETED = 4;
-
- const HTTP_CODE_OK = 200;
-
- // The delay between two refreshes when the sidebar is closed (in seconds)
- const YOUTUBE_REFRESH_INTERVAL = 3600; // 60 minutes
- // The delay between two refreshes when the sidebar is open (in seconds)
- const YOUTUBE_SHORT_INTERVAL = 3600; // 60 minutes
-
-
- var gCompTK;
- function getCompTK() {
- if (!gCompTK) {
- gCompTK = Cc["@flock.com/singleton;1"]
- .getService(Ci.flockISingleton)
- .getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
- .wrappedJSObject;
- }
- return gCompTK;
- }
-
- function _getIdentityUrn(aAccountId, aUid) {
- var result = YOUTUBE_IDENTITY_URN_PREFIX
- + aAccountId + ":"
- + aUid;
- return result;
- }
-
- loadLibraryFromSpec("chrome://browser/content/flock/photo/photoAPI.js");
-
- var gTimers = []; // For use with the scheduler
-
- // String defaults... may be updated later through Web Detective
- var gStrings = {
- "domains": "youtube.com",
- "userlogin": "http://www.youtube.com/login",
- "userprofile": "http://www.youtube.com/profile?user=%accountid%",
- "editprofile": "http://youtube.com/my_profile",
- "inbox": "http://youtube.com/my_messages",
- "noavatarimage": "no_videos_140.jpg"
- };
-
- function youtubeVideo() {
- }
-
- youtubeVideo.prototype= {
- id: "",
- thumbnail: "",
- webPageUrl: "",
- midSizePhoto: "",
- largeSizePhoto: "",
- title: "",
- username: "",
- userid: "",
- is_public: "true",
- is_video: "true",
- has_miniView: "true",
- svcShortName: 'youtube',
- buildTooltip: function( ) {
- // do we have to use document from the window to ceate elements? -- ja
- var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
- .getService(Ci.nsIWindowMediator);
- var win = wm.getMostRecentWindow('navigator:browser');
- if (!win) return null;
-
- var box = win.document.createElement('vbox');
- box.setAttribute('style', 'max-width: 250px');
-
- var title = win.document.createElement('label');
- title.setAttribute('value', this.title );
- title.setAttribute('crop', 'end');
- box.appendChild(title);
-
- if( this.length_seconds)
- {
- var lbl = win.document.createElement('label');
- lbl.setAttribute('value', 'Length: ' + this.length_seconds + ' seconds');
- box.appendChild(lbl);
- }
- if(this.rating_avg)
- {
- var lbl = win.document.createElement('label');
- lbl.setAttribute('value', 'Rating: ' + this.rating_avg + ' (' + this.rating_count + ' times)');
- box.appendChild(lbl);
- }
- if(this.view_count)
- {
- var lbl = win.document.createElement('label');
- lbl.setAttribute('value', 'Views: ' + this.view_count );
- box.appendChild(lbl);
- }
-
- if(!(this.length_seconds && this.rating_avg && this.view_count))
- {
- //if the tooltip does not these metadata -- show the author
- var lbl = win.document.createElement('label');
- lbl.setAttribute('value', this.username );
- lbl.setAttribute('class', 'user');
- box.appendChild(lbl);
- }
-
- var vbox = win.document.createElement('vbox');
- var cbox = win.document.createElement('cbox');
- var largeImg = win.document.createElement('image');
- largeImg.setAttribute('src', this.midSizePhoto);
- largeImg.setAttribute('style', 'margin-bottom: 2px;');
- var spacer = win.document.createElement('spacer');
- spacer.setAttribute('flex', '1');
- cbox.appendChild(largeImg);
- cbox.appendChild(spacer);
- vbox.appendChild(cbox);
- vbox.appendChild(box);
-
- return vbox;
- },
- buildHTML: function ( ) {
- var flashUrl = this.webPageUrl.replace(/\/\?v\=/,'/v/');
-
- return '<object width="425" height="350">'
- + '<param name="movie" value="'+flashUrl+'"/>'
- + '<embed src="'+flashUrl+'" type="application/x-shockwave-flash" width="425" height="350"/>'
- + this.webPageUrl
- + '</object>';
- },
- buildBBCode: function ( ) {
- var video = this.webPageUrl.replace(/\/\?v\=/,'/watch?v=');
- return '[youtube]' + video + '[/youtube]'
- },
- buildMiniPage: function ( ) {
- var theurl = this.webPageUrl.replace(/\/\?v\=/,'/v/');
- return '<html><head><title>' + this.title + ' (' + this.username + ')</title></head>' +
- '<body><object width="425" height="350">' +
- '<param name="movie" value="'+theurl+'"/>' +
- '<center><embed src="'+theurl+'&autoplay=1" type="application/x-shockwave-flash" width="425" height="350"/></object></center></body></html>';
- },
-
- QueryInterface: function(iid) {
- if (!iid.equals(Ci.nsISupports) &&
- !iid.equals(Ci.flockIPhoto)) {
- throw Components.results.NS_ERROR_NO_INTERFACE;
- }
- return this;
- }
- };
-
- youtubeVideo.prototype.__defineGetter__('metaData', function () {
- var metaData = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
- metaData.setPropertyAsAString("title", this.title);
- metaData.setPropertyAsAString("length", this.length_seconds);
- metaData.setPropertyAsAString("views", this.view_count);
- metaData.setPropertyAsAString("rating", this.rating_avg);
-
- metaData.QueryInterface(Ci.nsIPropertyBag);
-
- return metaData;
- })
-
-
- // ================================================
- // ========== BEGIN youtubeService class ==========
- // ================================================
-
- function youtubeService()
- {
- this.obs = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- this.obs.addObserver(this, OBS_TOPIC_XPCOMSHUTDOWN, false);
- this.acUtils = Components.classes["@flock.com/account-utils;1"]
- .getService(Components.interfaces.flockIAccountUtils);
- this.status = Components.interfaces.flockIWebService.STATUS_UNKNOWN;
- this.url = "http://www.youtube.com";
- this.mIsInitialized = false;
- this._ctk = {
- interfaces: [
- "nsISupports",
- "nsISupportsCString",
- "nsIClassInfo",
- "nsIObserver",
- "flockIWebService",
- "flockIMediaWebService",
- "flockISocialWebService",
- "flockIYoutubeService",
- "flockIManageableWebService",
- "flockIPollingService",
- "flockIRichContentDropHandler"
- ],
- shortName: "youtube",
- fullName: "YouTube",
- description: YOUTUBE_TITLE,
- favicon: YOUTUBE_FAVICON,
- CID: YOUTUBE_CID,
- contractID: YOUTUBE_CONTRACTID,
- accountClass: youtubeAccount,
- needPassword: false
- };
-
- var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
- .getService(Ci.nsIStringBundleService);
- var bundle = sbs.createBundle(YOUTUBE_STRING_BUNDLE);
-
- this._channels = {
- "special:added": {
- title: bundle.GetStringFromName("flock.youtube.title.added"),
- supportsSearch: false,
- feed: "http://youtube.com/rss/global/recently_added.rss"
- },
- "special:featured": {
- title: bundle.GetStringFromName("flock.youtube.title.featured"),
- supportsSearch: false
- },
- "special:top_favorites": {
- title: bundle.GetStringFromName("flock.youtube.title.topfav"),
- supportsSearch: false,
- feed: "http://youtube.com/rss/global/top_favorites.rss"
- },
- "special:rated": {
- title: bundle.GetStringFromName("flock.youtube.title.rated"),
- supportsSearch: false,
- feed: "http://youtube.com/rss/global/top_rated.rss"
- }
- };
-
- this._logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
- this._logger.init('youtube');
- this._profiler = Cc["@flock.com/profiler;1"].getService(Ci.flockIProfiler);
- this.init();
- }
-
-
- // BEGIN nsIObserver interface
- youtubeService.prototype.observe =
- function youtubeService_observe(subject, topic, state)
- {
- switch (topic) {
- case OBS_TOPIC_XPCOMSHUTDOWN:
- {
- this.obs.removeObserver(this, OBS_TOPIC_XPCOMSHUTDOWN);
- }; break;
- }
- }
- // END nsIObserver interface
-
-
- youtubeService.prototype.init =
- function youtubeService_init()
- {
- DEBUG(".init()");
-
- // Prevent re-entry
- if (this.mIsInitialized) return;
- this.mIsInitialized = true;
-
- var evtID = this._profiler.profileEventStart("youtube-init");
-
- this.prefService = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefBranch);
- if ( this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
- !this.prefService.getBoolPref(SERVICE_ENABLED_PREF) )
- {
- DEBUG("Pref "+SERVICE_ENABLED_PREF+" set to FALSE... not initializing.");
- var catMgr = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
- catMgr.deleteCategoryEntry("wsm-startup", CATEGORY_COMPONENT_NAME, true);
- catMgr.deleteCategoryEntry("flockWebService", CATEGORY_ENTRY_NAME, true);
- catMgr.deleteCategoryEntry("flockMediaProvider", CATEGORY_ENTRY_NAME, true);
- return;
- }
-
- this.faves_coop = Components.classes['@flock.com/singleton;1']
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
- this.account_root = this.faves_coop.accounts_root;
-
- this.ytService = new this.faves_coop.Service(
- "urn:youtube:service",
- {
- name: "youtube",
- desc: "The YouTube Service",
- loginURL: gStrings["userlogin"],
- contactLabel: 'Contacts'
- }
- );
- this.ytService.serviceId = YOUTUBE_CONTRACTID;
-
- // Load Web Detective file
- this.webDetective = this.acUtils.useWebDetective("youtube.xml");
- for (var s in gStrings) {
- gStrings[s] = this.webDetective.getString("youtube", s, gStrings[s]);
- }
- this.ytService.domains = gStrings["domains"];
-
- this.urn = this.ytService.id();
-
- this._updateFriendAvatarsComplete = false;
-
- this._updateFriendActivityComplete = false;
- this._friendActivityArray = [];
-
- this._profiler.profileEventEnd(evtID, "");
- }
-
- youtubeService.prototype.getError =
- function youtubeService_getError (aErrorType, aXML, aHTTPErrorCode) {
- var error = Components.classes["@flock.com/error;1"].createInstance(Ci.flockIError);
- if (aErrorType == "HTTP_ERROR") {
- error.errorCode = aHTTPErrorCode;
- } else if (aErrorType == "SERVICE_ERROR") {
- var errorCode;
- var errorMessage;
- var serviceErrorMessage;
- try {
- errorCode = aXML.getElementsByTagName("error")[0].getAttribute('code');
- serviceErrorMessage = aXML.getElementsByTagName("error")[0].getAttribute('description');
- } catch (ex) {
- errorCode = "999" // in case the error xml is invalid
- }
-
- switch (errorCode) { // http://www.youtube.com/dev_error_codes
- case "1":
- error.errorCode = error.HTTP_INTERNAL_SERVER_ERROR;
- break;
-
- case "2": // These errors are due to Flock sending a bad request
- case "3":
- case "4":
- case "5":
- case "6":
- error.errorCode = error.PHOTOSERVICE_INVALID_QUERY;
- break;
-
- case "7":
- case "8":
- error.errorCode = error.PHOTOSERVICE_INVALID_API_KEY;
- break;
-
- case "999":
- error.errorCode = error.PHOTOSERVICE_UNKNOWN_ERROR;
- break;
-
- default:
- error.errorCode = error.PHOTOSERVICE_UNKNOWN_ERROR;
- break;
- }
- }
- error.serviceErrorCode = errorCode;
- error.serviceErrorString = serviceErrorMessage;
- this._logger.error(error.errorString);
- return error;
- };
-
- youtubeService.prototype.supportsSearch =
- function youtubeService_supportsSearch( aQueryString ) {
- var aQuery = new queryHelper(aQueryString);
-
- if (aQuery.special) {
- var channel = this._channels["special:" + aQuery.special];
- if (channel) {
- return channel.supportsSearch;
- }
- }
-
- // none of the other apis/feeds support search
- return false;
- }
-
- youtubeService.prototype.call =
- function youtubeService_call(aListener, aMethod, aParams)
- {
- var url = "http://www.youtube.com/api2_rest?method=" + aMethod + "&dev_id=" + YT_DEVID;
- for (p in aParams) {
- url += "&" + p + "=" + aParams[p];
- }
- var hr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']
- .createInstance(Components.interfaces.nsIXMLHttpRequest)
- .QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
-
- var inst = this;
- hr.onreadystatechange = function (aEvt) {
- if (hr.readyState == 4) {
- try {
- if (hr.status/100 == 2) {
- var rsp = hr.responseXML.getElementsByTagName("ut_response")[0];
- var stat = rsp.getAttribute("status");
- if (stat != "ok") {
- var error = inst.getError('SERVICE_ERROR', hr.responseXML, null);
- aListener.onError(error);
- }
- else {
- aListener.onResult(hr.responseXML);
- }
- }
- else {
- // http errors
- aListener.onError(inst.getError("HTTP_ERROR", null, hr.status));
- }
- } catch(e) {
- // XMHTTPERROR (connection lost)
- inst._logger.error(e);
- aListener.onError(inst.getError("HTTP_ERROR", null, "9001"));
- }
- }
- };
-
- hr.backgroundRequest = true;
- hr.open('GET', url,true);
- hr.send(null);
- }
-
- youtubeService.prototype.getFeed =
- function youtubeService_getFeed(aListener, aFeedURL)
- {
- ios = Components.classes["@mozilla.org/network/io-service;1"]
- .getService(Components.interfaces.nsIIOService);
- var uri = ios.newURI(aFeedURL, null, null);
-
- var ytServ = this;
- var feedListener = {
- onGetFeedComplete: function oncomplete (feed) {
- ytServ.handleFeedResult(aListener, feed);
- },
- onError: aListener.onError
- };
-
- var fm = Components.classes["@flock.com/feed-manager;1"]
- .getService(Components.interfaces.flockIFeedManager);
- fm.getFeedBypassCache(uri, feedListener);
- }
-
- youtubeService.prototype.createAlbum =
- function youtubeService_createAlbum(aListener, aAlbumName)
- {
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
- }
-
- youtubeService.prototype.findByUsername =
- function youtubeService_findByUsername(aListener, aUsername)
- {
- var inst = this;
- var myListener = {
- onResult: function (aXML) {
- var newUserObj = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID]
- .createInstance(Components.interfaces.flockIPhotoPerson);
- newUserObj.service = inst;
- newUserObj.id = aUsername;
- newUserObj.username = aUsername;
- newUserObj.fullname = aUsername;
- aListener.onFindByUsernameResult(newUserObj);
- },
- onError: function (aXML) {
- aListener.onError(aXML);
- }
- }
- var params = {};
- params.user = aUsername;
- this.call(myListener, "youtube.users.get_profile", params);
- }
-
- youtubeService.prototype.getAlbums = function(aListener, aUsername) { throw Components.results.NS_ERROR_NOT_IMPLEMENTED; }
- youtubeService.prototype.getAuthPerson = function() {
- if (!this.user) return null;
- var newUserObj = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID]
- .createInstance(Components.interfaces.flockIPhotoPerson);
- newUserObj.id = this.api.user.username
- newUserObj.username = this.api.user.username;
- newUserObj.fullname = this.api.user.username;
- newUserObj.service = this;
- return newUserObj;
- }
- youtubeService.prototype.getContacts = function(aListener) { throw Components.results.NS_ERROR_NOT_IMPLEMENTED; }
- youtubeService.prototype.getMostRecentPhotoForList = function(aListener, aEnumerator) { throw Components.results.NS_ERROR_NOT_IMPLEMENTED; }
- youtubeService.prototype.getPhoto = function(aListener, aPhotoID) { throw Components.results.NS_ERROR_NOT_IMPLEMENTED; }
- youtubeService.prototype.login = function(aAccountURN, aListener) { throw Components.results.NS_ERROR_NOT_IMPLEMENTED; }
-
- youtubeService.prototype.queryChannel =
- function youtubeService_queryChannel(aListener, aQueryString, aCount, aPage)
- {
- var aQuery = new queryHelper(aQueryString);
- // return; // XXX TODO FIXME: This is killing perf
-
- var inst = this;
- var myListener = {
- onResult: function (aXML) {
- var rval = inst.handlePhotosResult(aXML);
- var enum_ = {
- hasMoreElements: function() {
- return (rval.length > 0);
- },
- getNext: function() {
- return rval.shift();
- }
- }
- aListener.onSearchResult(enum_);
- },
- onError: function (aError) {
- aListener.onError(aError);
- }
- }
-
- var params = {}
- if (aQuery.search) {
- params.tag = aQuery.search;
- params.page = aPage;
- params.per_page = aCount;
- this.call(myListener, 'youtube.videos.list_by_tag', params);
- } else {
- // this API call doesn't support pagination and only shows most recent 25 items
- if (aPage > 1) return;
-
- var channel = this._channels[aQuery.stringVal];
- if (!channel) return;
-
- if (channel.feed)
- this.getFeed(aListener, channel.feed);
- else
- this.call(myListener, "youtube.videos.list_featured", params);
- }
- }
-
- youtubeService.prototype.search =
- function youtubeService_search( aListener, aQueryString, aCount, aPage )
- {
- var aQuery = new queryHelper(aQueryString);
- if (aPage > 1) return; // youtube doesn't support pagination
- if(aQuery.favorites && !aQuery.user)
- {
- aQuery.user = aQuery.favorites;
- }
- if (!aQuery.user && aQuery.special != "favorites") {
- this.queryChannel( aListener, aQueryString, aCount, aPage );
- return;
- }
-
- var aUserid = aQuery.user;
-
- var params = {
- user: aUserid
- };
-
- var inst = this;
- var myListener = {
- onResult: function (aXML) {
- var rval = inst.handlePhotosResult(aXML, aUserid);
- var enum_ = {
- hasMoreElements: function() {
- return (rval.length > 0);
- },
- getNext: function() {
- return rval.shift();
- }
- }
- aListener.onSearchResult(enum_);
- },
- onError: function (aError) {
- aListener.onError(aError);
- }
- }
-
- if (aQuery.favorites) {
- this.call(myListener, "youtube.users.list_favorite_videos", params);
- } else {
- this.call(myListener, "youtube.videos.list_by_user", params);
- }
- }
-
- youtubeService.prototype.getPhotoFromRDFNode =
- function (aRDFId)
- {
- var newPhoto = new youtubeVideo();
- var coopPhoto = this.faves_coop.get(aRDFId);
- newPhoto.webPageUrl = coopPhoto.URL;
- newPhoto.thumbnail = coopPhoto.thumbnail;
- newPhoto.midSizePhoto = coopPhoto.midSizePhoto;
- newPhoto.largeSizePhoto = coopPhoto.largeSizePhoto;
- newPhoto.username = coopPhoto.username;
- newPhoto.userid = coopPhoto.userid;
- newPhoto.title = coopPhoto.name;
- newPhoto.id = coopPhoto.photoid;
- newPhoto.icon = coopPhoto.favicon;
- newPhoto.uploadDate = coopPhoto.datevalue;
- newPhoto.is_public = coopPhoto.is_public;
- newPhoto.is_video = "true";
- return newPhoto;
- // JMC XXX TODO: Gotta add the video-specific fields into the RDF, or somewhere
- // eg content length, rating, etc.
-
- }
-
- youtubeService.prototype.handlePhotosResult =
- function youtubeService_handlePhotoResult(aXML, aUserid)
- {
- var rval = [];
- var photoList = aXML.getElementsByTagName("video");
- for (var i = 0; i < photoList.length; i++) {
- var photo = photoList[i];
- var newPhoto = new youtubeVideo();
- for (var j = 0; j < photo.childNodes.length; j++)
- {
- var child = photo.childNodes[j];
- var contentNode = child.childNodes[0];
- var childContent = "";
- if (contentNode) childContent = contentNode.nodeValue;
- switch (child.tagName)
- {
- case "author":
- newPhoto.username = childContent;
- newPhoto.userid = childContent;
- break;
- // case "id": newPhoto.id = childContent; break;
- case "title": newPhoto.title = childContent; break;
- case "upload_time":
- newPhoto.uploadDate = childContent * 1000;
- newPhoto.id = parseInt(childContent);
- break;
- case "length_seconds":
- newPhoto.length_seconds = childContent;
- break
- case "rating_avg":
- newPhoto.rating_avg = childContent;
- break
- case "description":
- newPhoto.description = childContent;
- break
- case "comment_count":
- newPhoto.comment_count = childContent;
- break
- case "view_count":
- newPhoto.view_count = childContent;
- break
- case "rating_count":
- newPhoto.rating_count = childContent;
- break
- case "url":
- newPhoto.webPageUrl = childContent;
- break;
- case "thumbnail_url":
- newPhoto.thumbnail = childContent;
- newPhoto.midSizePhoto = childContent;
- newPhoto.largeSizePhoto = childContent;
- break;
- // case "id": newPhoto.id = childContent;
- // break;
- }
- }
-
- newPhoto.is_public = "true";
- newPhoto.is_video = true;
- rval.push(newPhoto);
- }
- return rval;
- }
-
- youtubeService.prototype.handleFeedResult =
- function youtubeService_handleFeedResult(aListener, aFeed)
- {
- var photos = [];
-
- var items = aFeed.getItems();
- while (items && items.hasMoreElements()) {
- var item = items.getNext();
-
- var newPhoto = new youtubeVideo();
-
- newPhoto.title = item.getTitle();
- newPhoto.webPageUrl = item.getLink().spec;
-
- newPhoto.uploadDate = item.getPubDate();
- newPhoto.id = newPhoto.uploadDate / 1000;
-
- var author = item.getAuthor();
- newPhoto.username = author;
- newPhoto.userid = author;
-
- var desc = item.getContent();
- var re = /<img [^>]*src="([^"]*)"/i;
- var thumbnail = desc.match(re)[1];
- newPhoto.thumbnail = thumbnail;
- newPhoto.midSizePhoto = thumbnail;
- newPhoto.largeSizePhoto = thumbnail;
-
- newPhoto.is_public = "true";
- newPhoto.is_video = true;
-
- photos.push(newPhoto);
- }
-
- var enum_ = {
- hasMoreElements: function() {
- return (photos.length > 0);
- },
- getNext: function() {
- return photos.shift();
- }
- }
- aListener.onSearchResult(enum_);
- }
-
-
- youtubeService.prototype.supportsFeature = function(aFeature) {
- var supports = {};
- supports.tags = true;
- supports.title = true;
- supports.fileName = false;
- supports.contacts = true;
- supports.privacy = false;
- supports.albumCreation = false;
- return (supports[aFeature] == true);
- }
- youtubeService.prototype.upload = function(aListener, aFile, aParams, aUpload) { throw Components.results.NS_ERROR_NOT_IMPLEMENTED; }
-
-
- youtubeService.prototype.refresh =
- function youtubeService_refresh(aURN, aListener)
- {
- DEBUG("refresh with aURN of " + aURN);
- var refreshItem = this.faves_coop.get(aURN);
-
- if (refreshItem.isInstanceOf(this.faves_coop.Account)) {
- this._logger.debug("refreshing an Account");
- if (refreshItem.isAuthenticated) {
- this.refreshAccount(aURN, aListener);
- } else {
- // If the user is not logged in, return a success without
- // refreshing anything
- aListener.onResult();
- }
- } else {
- throw Components.results.NS_ERROR_ABORT;
- }
- }
-
- youtubeService.prototype.refreshAccount =
- function youtubeService_refreshAccount(aURN, aListener)
- {
- if (!aURN) return;
- var inst = this;
- var coopAcct = this.faves_coop.get(aURN);
- var individualSuccess = {};
- individualSuccess.numberOfAnswers = 0;
- individualSuccess.listener = aListener;
- individualSuccess.coopAcct = coopAcct;
- individualSuccess.refreshNumber = 3;
-
- // get friends
- var getFriendsListener = {
- onResult: function getFriendsListener_onResult(aXML) {
- inst._handleFriendsResult(aXML, coopAcct, individualSuccess);
- },
- onError: function getFriendsListener_onError(aXML) {
- inst._logger.error("Error on getFriendsListener");
- }
- }
-
- // get new message count
- var hr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
- .createInstance(Ci.nsIXMLHttpRequest);
- hr.onreadystatechange = function updateUserAccount_onreadystatechange(aEvent) {
- if (hr.readyState == 4) {
- var results = Cc["@mozilla.org/hash-property-bag;1"]
- .createInstance(Ci.nsIWritablePropertyBag2);
- if (inst.webDetective.detectNoDOM("youtube", "accountinfo", "",
- hr.responseText, results))
- {
- // Set the message count
- var messages = 0;
- var msgCount = results.getPropertyAsAString("messages");
- if (msgCount && msgCount.length) {
- messages = msgCount;
- }
- inst._logger.debug("coopAcct.accountMessages " + messages);
- if (coopAcct.accountMessages < messages) {
- inst._lightPeopleIcon();
- }
- coopAcct.accountMessages = messages;
-
- // Set the avatar for the mecard.
- // If avatar returned as YT no avatar, then set coop avatar to
- // null and let people sidebar code set the Flock no avatar img.
- if (results.getPropertyAsAString("avatar")
- .match(gStrings["noavatarimage"])) {
- coopAcct.avatar = null;
- inst._logger.debug("no avatar for account, setting to null\n");
- } else {
- var avatar = results.getPropertyAsAString("avatar");
- coopAcct.avatar = inst._fixRelativeAvatarUrl(avatar);
- inst._logger.debug("coopAcct.accountAvatar " + coopAcct.avatar);
- }
- } else {
- coopAcct.accountMessages = 0;
- }
- inst._onIndividualSuccess(individualSuccess);
- }
- }
- hr.open("GET", gStrings["userprofile"].replace("%accountid%", coopAcct.id()));
- hr.send(null);
-
- var params = {};
- params.user = coopAcct.accountId;
- this.call(getFriendsListener, "youtube.users.list_friends", params);
- }
-
- youtubeService.prototype._onIndividualSuccess =
- function youtubeService__onIndividualSuccess(aObj) {
- aObj.numberOfAnswers++;
- if (aObj.numberOfAnswers >= aObj.refreshNumber) {
- if (this.acUtils.isPeopleSidebarOpen()) {
- aObj.coopAcct.nextRefresh = new Date(Date.now()
- + YOUTUBE_SHORT_INTERVAL * 1000);
- }
- if (aObj.listener) {
- aObj.listener.onResult();
- }
- }
- }
-
- youtubeService.prototype.markAllMediaSeen =
- function youtubeService_markAllMediaSeen(aIdentityUrn) {
- var identity = this.faves_coop.get(aIdentityUrn);
- identity.unseenMedia = 0;
- }
-
- youtubeService.prototype._lightPeopleIcon =
- function youtubeService__lightPeopleIcon() {
- this._logger.debug("._lightPeopleIcon()");
- this.obs.notifyObservers(null, "new-people-notification", null);
- }
-
- youtubeService.prototype._updateFriendAvatars =
- function youtubeService__updateFriendAvatars(aURN, aInvidualSuccessObj) {
- this._logger.info("._updateFriendAvatars");
-
- if (this._updateFriendAvatarsComplete || !aURN) {
- return;
- }
-
- // Array of friends accounts (coop objects, not URNs) used to get avatars
- var friendsList = [];
-
- // Retrieve the account's friends list and add friends currently without an
- // avatar to a list to be updated at a later time
- var friendsEnum = this.faves_coop.get(aURN).friendsList.children.enumerate();
- while (friendsEnum.hasMoreElements()) {
- var friend = friendsEnum.getNext();
- if (friend.avatar == "") {
- this._logger.debug("adding friend with missing avatar for updating: "
- + friend.accountId + "\n");
- friendsList.push(friend);
- // Increment number count that onIndividualSucess needs to count to
- aInvidualSuccessObj.refreshNumber++;
- }
- }
-
- var inst = this;
-
- var friendsTimerCallback = {
- notify: function friendNotify(aTimer) {
- // Scrape the friend page for their avatar
- if (friendsList.length > 0) {
- var friend = friendsList.shift();
- var page = gStrings["userprofile"]
- .replace("%accountid%", friend.accountId);
- var xhr = Cc[XHR_CONTRACTID].createInstance(Ci.nsIXMLHttpRequest);
- xhr.open("GET", page, true);
-
- xhr.onreadystatechange = function friend_OnReadyStateChange(aEvent) {
- if (xhr.readyState == XMLHTTPREQUEST_READYSTATE_COMPLETED) {
- if (xhr.status == HTTP_CODE_OK) {
- var results = Cc[PROPERTY_BAG_CONTRACTID]
- .createInstance(Ci.nsIWritablePropertyBag2);
- if (inst.webDetective.detectNoDOM("youtube", "page", "",
- xhr.responseText, results))
- {
- // If avatar returned as YT no avatar, then set coop avatar to
- // null and let people sidebar code set the Flock no avatar img.
- if (results.getPropertyAsAString("avatar")
- .match(gStrings["noavatarimage"])) {
- friend.avatar = null;
- inst._logger.debug("no avatar for friend: " + friend.accountId + "\n");
- } else {
- friend.avatar = results.getPropertyAsAString("avatar");
- friend.avatar = inst._fixRelativeAvatarUrl(friend.avatar);
- inst._logger.debug("found friend's avatar: " + friend.accountId
- + ", " + friend.avatar + "\n");
- }
- }
- inst._onIndividualSuccess(aInvidualSuccessObj);
- }
- }
- }
-
- inst._logger.debug("requesting avatar for: " + page + "\n");
- xhr.send(null);
- }
-
- // Kill the timer if there's nothing left to update in the array
- if (friendsList.length < 1) {
- inst._logger.debug("no friends without avatars left to update, "
- + "kill the timer");
- inst._friendsTimer.cancel();
- inst._friendsTimer = null;
- }
- }
- };
-
- // Start the timer to update the account's friends avatars
- if (!this._friendsTimer && friendsList.length > 0) {
- this._logger.debug("found friends without avatars to update, "
- + "start the timer");
- this._friendsTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- this._friendsTimer.initWithCallback(friendsTimerCallback,
- FRIENDS_AVATAR_TIMEOUT,
- Ci.nsITimer.TYPE_REPEATING_SLACK);
-
- // Once we've started updating friends without avatars, we only want to
- // check once per session so as not to incur a performance hit
- this._updateFriendAvatarsComplete = true;
- }
- }
-
- youtubeService.prototype._updateFriendAvatar =
- function youtubeService__updateFriendAvatar(aDocument, aAccountID) {
- if (aDocument && aAccountID) {
- var results = Cc[PROPERTY_BAG_CONTRACTID]
- .createInstance(Ci.nsIWritablePropertyBag2);
-
- if (this.webDetective.detect("youtube", "page", aDocument, results)) {
- var friendID = results.getPropertyAsAString("friend");
-
- // Only need to update the friend avatar if we're visiting the friend's page
- if (aAccountID != friendID) {
- var friendURN = _getIdentityUrn(aAccountID, friendID);
- if (friendURN) {
- var friend = this.faves_coop.get(friendURN);
- var avatar = results.getPropertyAsAString("avatar");
- avatar = this._fixRelativeAvatarUrl(avatar);
-
- // Only need to update the friend avatar if it's changed
- if (friend && friend.avatar != avatar) {
- friend.avatar = avatar;
- }
- }
- }
- }
- }
- }
-
- /**
- * The avatar URL we scraped may be a relative URL. If so, prepend
- * "http://www.youtube.com/" to it.
- */
- youtubeService.prototype._fixRelativeAvatarUrl =
- function youtubeService__fixRelativeAvatarUrl(aUrl) {
- var url = aUrl;
-
- if (url.indexOf("http") != 0) {
- url = "http://www.youtube.com";
- // Do we need to add a leading slash?
- if (aUrl.indexOf("/") != 0) {
- url += "/";
- }
- url += aUrl;
- }
-
- return url;
- }
-
- youtubeService.prototype._personUpdateRequired =
- function youtubeService__personUpdateRequired(aCoopPerson, aPerson) {
- return (aCoopPerson.name != aPerson.accountId);
- }
-
- youtubeService.prototype.addCoopPerson =
- function youtubeService_addCoopPerson(aPhotoPerson, aCoopAccount)
- {
- var person = aPhotoPerson;
- var identityUrn = _getIdentityUrn(aCoopAccount.accountId,
- person.accountId);
- var updating = this.faves_coop.Identity.exists(identityUrn);
- var identity;
- if (updating) {
- identity = this.faves_coop.get(identityUrn);
- if (this._personUpdateRequired(aCoopAccount,person)) {
- // Update data of the identity coop obj here
- identity.name = person.accountId;
- this._incrementMedia(identity, person);
- }
- } else {
- identity = new this.faves_coop.Identity(
- identityUrn,
- {
- name: person.accountId,
- serviceId: YOUTUBE_CONTRACTID,
- accountId: person.accountId,
- avatar: "",
- statusMessage: "",
- lastUpdateType: "media",
- lastUploadedMedia: person.videoCount
- }
- );
- aCoopAccount.friendsList.children.add(identity);
- this._addIdentityToActivityArray(identity);
- }
- }
-
- youtubeService.prototype._addIdentityToActivityArray =
- function youtubeService__addIdentityToActivityArray(aIdentity) {
- this._logger.info("._addIdentityToActivityArray('"+ aIdentity.name + "')");
-
- //only want to add to array when friendsActivity timer is ready
- if (!this._updateFriendActivityComplete) {
- this._friendActivityArray.push(aIdentity);
- }
- }
-
- youtubeService.prototype._incrementMedia =
- function youtubeService__incrementMedia(identity, person) {
- this._logger.info("._incrementMedia('"+identity.id() + "," + person.accountId +"')");
-
- if (identity.lastUploadedMedia != person.videoCount) {
- identity.lastUploadedMedia = person.videoCount;
- identity.unseenMedia = 1;
- this._addIdentityToActivityArray(identity);
- }
- }
-
- youtubeService.prototype._updateFriendRecentActivity =
- function youtubeService__updateFriendRecentActivity(aIndividualSuccess) {
- this._logger.info("._updateFriendRecentActivity");
- var success = aIndividualSuccess;
- if (this._updateFriendActivityComplete ||
- this._friendActivityArray.length == 0)
- {
- this._onIndividualSuccess(success);
- return;
- }
- // We are successful for refresh after each friend in _friendActivityArray
- // list is updated
- success.refreshNumber += (this._friendActivityArray.length -1);
- var inst = this;
-
- var friendsTimerCallback = {
- notify: function friendNotify(aTimer) {
- inst._updateFriendActivityComplete = true;
- while(inst._friendActivityArray.length != 0)
- {
- var identity = inst._friendActivityArray.pop();
- inst._updateLastUpdateDate(identity, success);
- inst._logger.info("updating recent activity for " + identity.name);
- }
- inst._logger.debug("no friends without avatars left to update, "
- + "kill the timer");
- inst._friendsActivityTimer.cancel();
- inst._friendsActivityTimer = null;
- inst._updateFriendActivityComplete = false;
- inst._friendActivityArray = null;
- inst._friendActivityArray = [];
- inst._logger.info("done updating recent activity");
- }
- };
-
- // Start the timer to update the account's friends avatars
- if (!this._friendsActivityTimer) {
- this._logger.debug("found friends without avatars to update, "
- + "start the timer");
- this._friendsActivityTimer = Cc["@mozilla.org/timer;1"]
- .createInstance(Ci.nsITimer);
- this._friendsActivityTimer.initWithCallback(friendsTimerCallback,
- FRIENDS_ACTIVITY_TIMEOUT,
- Ci.nsITimer.TYPE_REPEATING_SLACK);
- this._updateFriendActivityComplete = false;
- }
- }
-
- youtubeService.prototype._updateLastUpdateDate =
- function youtubeService__updateLastUpdateDate(aIdentity, aInvidualSuccessObj)
- {
- this._logger.info("._updateLastUpdateDate('"+ aIdentity.name + "')");
-
- var identity = aIdentity;
- var params = {
- user: identity.name,
- page: 1,
- per_page: 1,
- };
-
- var inst = this;
- var myListener = {
- onResult: function (aXML) {
- inst._logger.info("onResult");
- var video = inst.handlePhotosResult(aXML);
- if (video.length == 1) {
- video = video[0];
- //Youtube gives us UNIX time in seconds, change to miliseconds
- var time = video.uploadDate / 1000;
- identity.lastUpdate = time;
- }
- inst._onIndividualSuccess(aInvidualSuccessObj);
- },
- onError: function (aError) {
- if (!identity.lastUpdate) {
- identity.lastUpdate = inst._numberFromString(identity.name);
- }
- }
- };
-
- this.call(myListener, "youtube.videos.list_by_user", params);
- }
-
- youtubeService.prototype._handleFriendsResult =
- function youtubeService__handleFriendsResult(aXML, aAccount,
- aInvidualSuccessObj)
- {
- DEBUG("._handleFriendsResult(aXML, aAccount)");
-
- var friendList = aXML.getElementsByTagName("friend");
- var inst = this;
- var peopleHash = [];
- DEBUG(" - found "+friendList.length+" friends");
- for (var i = 0; i < friendList.length; i++) {
- var friend = friendList[i];
- var friendObj = {};
- for (var j = 0; j < friend.childNodes.length; j++)
- {
- var child = friend.childNodes[j];
- var contentNode = child.childNodes[0];
- var childContent = "";
- if (contentNode) childContent = contentNode.nodeValue;
- switch (child.tagName)
- {
- case "user":
- friendObj.accountId = childContent;
- friendObj.name = childContent;
- break;
- case "video_upload_count":
- friendObj.videoCount = childContent;
- break;
- }
- }
- peopleHash[friendObj.accountId] = friendObj;
- peopleHash[friendObj.accountId].media = {
- count: 1,
- latest: friendObj.videoCount
- };
- }
- function myWorker(aShouldYield) {
- // ADD or update existing people
- for (var uid in peopleHash) {
- inst.addCoopPerson(peopleHash[uid], aAccount);
- if (aShouldYield()) {
- yield;
- }
- }
-
- // REMOVE locally people removed on the server
- var localEnum = aAccount.friendsList.children.enumerate();
- while (localEnum.hasMoreElements()) {
- var identity = localEnum.getNext();
- if (!peopleHash[identity.accountId]) {
- inst._logger.info("Friend " + identity.accountId
- + " has been deleted on the server");
- aAccount.friendsList.children.remove(identity);
- identity.destroy();
- }
- }
- inst._onIndividualSuccess(aInvidualSuccessObj);
- inst._updateFriendRecentActivity(aInvidualSuccessObj);
- inst._updateFriendAvatars(aAccount.id(), aInvidualSuccessObj);
- } // end myWorker()
-
- FlockScheduler.schedule(null, 0.05, 10, myWorker);
- }
-
- var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Components.interfaces.mozIJSSubScriptLoader);
- loader.loadSubScript("chrome://browser/content/utilityOverlay.js");
-
- // BEGIN flockIWebService interface
- youtubeService.prototype.addAccountById =
- function youtubeService_addAccountById(aAccountID, aIsTransient, aListener)
- {
- DEBUG("{flockIWebService}.addAccountById('"+aAccountID+"', "+aIsTransient+", aListener)");
-
- var accountURN = "urn:flock:youtube:"+aAccountID;
- var account = this.faves_coop.get(accountURN);
- if (!account) {
- account = new this.faves_coop.Account(
- accountURN,
- {
- name: aAccountID,
- serviceId: YOUTUBE_CONTRACTID,
- service: this.ytService,
- accountId: aAccountID,
- URL: gStrings["userprofile"].replace("%accountid%", aAccountID),
- isTransient: aIsTransient,
- refreshInterval: YOUTUBE_REFRESH_INTERVAL,
- favicon: YOUTUBE_FAVICON
- }
- );
- this.account_root.children.add(account);
- }
- if (!account.friendsList) {
- var friendsListUrn = accountURN + ":friends";
- var friendsList = new this.faves_coop.FriendsList(
- friendsListUrn,
- {
- account: account
- }
- );
- account.friendsList = friendsList;
- }
- this.USER = account.id();
-
- // Instanciate account component
- var acct = this.getAccount(account.id());
- if (aListener) aListener.onSuccess(acct, "addAccount");
- return acct;
- }
- // END flockIWebService interface
-
-
- // BEGIN flockIManageableWebService interface
- youtubeService.prototype.updateAccountStatusFromDocument =
- function youtubeService_updateAccountStatusFromDocument(aDocument)
- {
- this._logger.info("{flockIManageableWebService}.updateAccountStatusFromDocument()");
- if (this.webDetective.detect("youtube", "loggedout", aDocument, null))
- {
- this.acUtils.markAllAccountsAsLoggedOut(YOUTUBE_CONTRACTID);
- } else if (this.webDetective.detect("youtube", "loggedin", aDocument, null)) {
- var results = Components.classes["@mozilla.org/hash-property-bag;1"]
- .createInstance(Components.interfaces.nsIWritablePropertyBag2);
- if (this.webDetective.detect("youtube", "accountinfo", aDocument, results)) {
- var accountID = results.getPropertyAsAString("accountid");
- if (accountID && accountID.length) {
- var accountURN = this.acUtils.getAccountURNById(this.urn, accountID);
- var acct = this.faves_coop.get(accountURN);
- if (!acct.isAuthenticated) {
- var inst = this;
- var loginListener = {
- onSuccess: function loginListener_onSuccess() {
- inst._logger.debug(".updateAccountStatusFromDocument(): "
- + "loginListener: onSuccess()");
- acct.isAuthenticated = true;
- inst._updateFriendAvatarsComplete = false;
- },
- onError: function loginListener_onError(aError) {
- inst._logger.debug(".updateAccountStatusFromDocument(): "
- + "loginListener: onError()");
- inst._logger.debug(aError ? (aError.errorString) : "No details");
- }
- };
- this.getAccount(accountURN).login(loginListener);
- }
- }
- }
- }
- }
- // END flockIManageableWebService interface
-
-
- // BEGIN flockISocialWebService interface
- // END flockISocialWebService interface
-
-
- // BEGIN flockIMediaWebService interface
-
- youtubeService.prototype.migrateAccount =
- function youtubeService_migrateAccount(aId, aUsername) {
- this.init();
- this.addAccountById(aId, false, null);
- }
-
- youtubeService.prototype.decorateForMedia =
- function youtubeService_decorateForMedia(aDocument)
- {
- DEBUG("{flockIMediaWebService}.decorateForMedia(aDocument)");
- aDocument.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
- var results = Components.classes["@mozilla.org/hash-property-bag;1"]
- .createInstance(Components.interfaces.nsIWritablePropertyBag2);
- if (this.webDetective.detect("youtube", "media", aDocument, results)) {
- var mediaArr = [];
-
- // media item for user videos
- var userid = results.getPropertyAsAString("userid");
- var media = {
- name: userid,
- query: 'user:' + userid + "|username:" + userid,
- label: userid + "'s Videos", // FIXME: breaks internationalization
- favicon: this.icon,
- service: this.shortName
- }
- mediaArr.push(media);
-
- // media item for user favorites
- var media = {
- name: userid,
- query: 'favorites:' + userid,
- label: userid + "'s Favorites", // FIXME: breaks internationalization
- favicon: this.icon,
- service: this.shortName
- }
- mediaArr.push(media);
-
- if (!aDocument._flock_decorations) {
- aDocument._flock_decorations = {};
- }
- aDocument._flock_decorations.mediaArr = mediaArr;
- this.obs.notifyObservers(aDocument, 'media', 'media:update');
- }
- }
-
- youtubeService.prototype.handlesMediaStream =
- function youtubeService_handlesMediaStream()
- {
- return true;
- }
-
- youtubeService.prototype.checkIsStreamUrl =
- function youtubeService_checkIsStreamUrl(aUrl)
- {
- if (this.webDetective.detectNoDOM("youtube", "isStreamUrl", "", aUrl, null)) {
- this._logger.debug("Checking if url is youtube stream: YES: " + aUrl);
- return true;
- }
- this._logger.debug("Checking if url is youtube stream: NO: " + aUrl);
- return false;
- }
-
- youtubeService.prototype.getVideoIDFromUrl =
- function youTubeService_getVideoIDFromUrl(aUrl)
- {
- var videoId = null;
- //http://www.youtube.com/v/lp_daXRkOH0
- //http://www.youtube.com/watch/v/YP2rgi978tw
- //http://www.youtube.com/watch?v=BjfbS_Kj-J0
- // /player2.swf?video_id=xPxDw7ajfGE&....
- var detectResults = Cc["@mozilla.org/hash-property-bag;1"]
- .createInstance(Ci.nsIWritablePropertyBag2);
- if (this.webDetective.detectNoDOM("youtube", "videoId", "", aUrl, detectResults)) {
- videoId = detectResults.getPropertyAsAString("videoId");
- }
- return videoId;
- }
-
- youtubeService.prototype.getMediaQueryFromURL =
- function youTubeService_getMediaQueryFromURL(aUrl, aListener)
- {
- var videoId = this.getVideoIDFromUrl(aUrl);
- if (videoId) {
- var myListener = {
- onResult: function (aXML) {
- var userID = aXML.getElementsByTagName('author')[0].firstChild.nodeValue;
- var results = Components.classes["@mozilla.org/hash-property-bag;1"]
- .createInstance(Components.interfaces.nsIWritablePropertyBag2);
- results.setPropertyAsAString("query", "user:" + userID + "|username:" + userID);
- // Note: The "title" property is currently not used by the media bar.
- results.setPropertyAsAString("title", userID);
- aListener.onSuccess(results, "query");
- },
- onError: function (aError) {
- aListener.onError(null, aError, null);
- }
- }
- var params = {};
- params.video_id = videoId;
- this.call(myListener, "youtube.videos.get_details", params);
- } else {
- aListener.onError(null, "Unable to get user.", null);
- }
- }
- // END flockIMediaWebService interface
-
-
- // Checks if the TEXTAREA is drag and droppable
- youtubeService.prototype._isDnDableTextarea =
- function youtubeService__isDnDableTextarea(aDocument, aXPath, aTextarea)
- {
- if (aDocument && aXPath && aTextarea) {
- var xpath = this.webDetective.getString("youtube", aXPath, "");
- var results = aDocument.evaluate(xpath, aDocument, null,
- Ci.nsIDOMXPathResult.ANY_TYPE, null);
- if (results && results.iterateNext() == aTextarea) {
- return true;
- }
- }
- return false;
- }
-
-
- // BEGIN flockIRichContentDropHandler
- youtubeService.prototype.handleDrop =
- function youtubeService_handleDrop(aFlavours, aTextarea)
- {
- this._logger.info(".handleDrop()");
-
- var dropCallback = function youtube_dropCallback(aFlav) {
- var data = {}, len = {};
- aFlavours.getTransferData(aFlav, data, len);
- var caretPos = aTextarea.selectionEnd;
- var currentValue = aTextarea.value;
- // Add a trailing space so that we don't mangle the url
- var nextChar = currentValue.charAt(caretPos);
- var trailingSpace = ((nextChar == "") ||
- (nextChar == " ") ||
- (nextChar == "\n"))
- ? ""
- : " ";
- // Only add a breadcrumb if the insertion point is at the end of
- // the text so that we don't duplicate breadcrumbs
- var breadcrumb = (aTextarea.value.length == aTextarea.selectionEnd)
- ? Cc[FLOCK_RDDS_CONTRACTID]
- .getService(Ci.flockIRichDNDService)
- .getBreadcrumb("plain")
- : "";
-
- aTextarea.value = currentValue.substring(0, caretPos)
- + data.value.QueryInterface(Ci.nsISupportsString)
- .data.replace(/: /, ":\n")
- + trailingSpace
- + currentValue.substring(caretPos)
- + breadcrumb;
- };
-
- return this._handleTextareaDrop(CATEGORY_ENTRY_NAME, this.ytService.domains,
- aTextarea, dropCallback);
- }
- // END flockIRichContentDropHandler
-
- youtubeService.prototype.maxStatusLength = 0;
-
- // ========== END youtubeService class ==========
-
-
-
- // ================================================
- // ========== BEGIN youtubeAccount class ==========
- // ================================================
-
- function youtubeAccount()
- {
- this.acUtils = Components.classes["@flock.com/account-utils;1"]
- .getService(Components.interfaces.flockIAccountUtils);
- this.service = Components.classes[YOUTUBE_CONTRACTID]
- .getService(Components.interfaces.flockIWebService)
- .QueryInterface(Components.interfaces.flockISocialWebService);
- this._coop = Components.classes["@flock.com/singleton;1"]
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
- this.webDetective = Cc["@flock.com/web-detective;1"]
- .getService(Ci.flockIWebDetective);
- this._ctk = {
- interfaces: [
- "nsISupports",
- "flockIWebServiceAccount",
- "flockIMediaWebServiceAccount",
- "flockISocialWebServiceAccount",
- "flockIYoutubeAccount"
- ]
- };
- getCompTK().addAllInterfaces(this);
-
- this._logger = Cc["@flock.com/logger;1"].createInstance(Ci.flockILogger);
- this._logger.init("youtubeAccount");
- }
-
-
- // BEGIN flockIWebServiceAccount interface
- youtubeAccount.prototype.urn = "";
- youtubeAccount.prototype.username = "";
- youtubeAccount.prototype.status = "";
-
- youtubeAccount.prototype.activate =
- function youtubeAccount_activate(aListener)
- {
- DEBUG("{flockIWebServiceAccount}.activate()");
- var acctCoopObj = this._coop.get(this.urn);
- acctCoopObj.isPollable = true;
- if (aListener) {
- aListener.onSuccess(this, "accountAuthorized");
- }
- }
-
- youtubeAccount.prototype.login =
- function youtubeAccount_login(aListener)
- {
- DEBUG("{flockIWebServiceAccount}.login()");
- this.acUtils.ensureOnlyAuthenticatedAccount(this.urn);
- // force refresh on login
- var pollerSvc = Cc["@flock.com/poller-service;1"]
- .getService(Ci.flockIPollerService);
- pollerSvc.forceRefresh(this.urn);
- aListener.onSuccess();
- }
- // END flockIWebServiceAccount interface
-
-
- // BEGIN flockISocialWebServiceAccount interface
- youtubeAccount.prototype.hasFriendActions = true;
- youtubeAccount.prototype.isStatusSupported = false;
- youtubeAccount.prototype.isStatusEditable = false;
- youtubeAccount.prototype.isPostLinkSupported = false;
- youtubeAccount.prototype.isMyMediaFavoritesSupported = true;
-
- youtubeAccount.prototype.setStatus =
- function youtubeAccount_setStatus(aStatusMessage, aListener)
- {
- this._logger.info("{flockISocialWebServiceAccount}.setStatus('"+aStatusMessage+"',"+
- "'"+aListener+"')");
- }
-
- youtubeAccount.prototype.getEditableStatus =
- function youtubeAccount_getEditableStatus()
- {
- this._logger.info("{flockISocialWebServiceAccount}.getEditableStatus()");
- return "";
- }
-
- youtubeAccount.prototype.formatStatusForDisplay =
- function youtubeAccount_formatStatusForDisplay(aStatusMessage)
- {
- return "";
- }
-
- youtubeAccount.prototype.getMeNotifications =
- function youtubeAccount_getMeNotifications()
- {
- this._logger.info(".getMeNotifications()");
-
- var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
- .getService(Ci.nsIStringBundleService);
- var bundle = sbs.createBundle(YOUTUBE_STRING_BUNDLE);
-
- var noties = [];
- var inst = this;
- function _addNotie(aType, aCount) {
- var stringName = "flock.youtube.noties."
- + aType + "."
- + ((parseInt(aCount) <= 0) ? "none" : "some");
- inst._logger.info("aType " + aType + ' aCount ' + aCount + ' name ' + stringName);
- noties.push({
- class: aType,
- tooltip: bundle.GetStringFromName(stringName),
- metricsName: aType,
- count: aCount,
- URL: inst.webDetective.getString("youtube", aType + "_URL", "")
- });
- }
- var c_acct = this._coop.get(this.urn);
- _addNotie("meMessages", c_acct.accountMessages);
- return JSON.toString(noties);
- }
-
- youtubeAccount.prototype.markAllMeNotificationsSeen =
- function youtubeAccount_markAllMeNotificationsSeen(aType) {
- this._logger.debug(".markAllMeNotificationsSeen('" + aType + "')");
- var c_acct = this._coop.get(this.urn);
- switch (aType) {
- case "meMessages":
- c_acct.accountMessages = 0;
- break;
- default:
- break;
- }
- }
-
- youtubeAccount.prototype.getFriendActions =
- function youtubeAccount_getFriendActions(aFriendURN)
- {
- this._logger.info(".getFriendActions('" + aFriendURN + "')");
-
- var actionNames = ["friendMessage",
- "friendViewProfile",
- "friendMediaFave",
- "friendShareFlock"];
-
- var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
- .getService(Ci.nsIStringBundleService);
- var bundle = sbs.createBundle(YOUTUBE_STRING_BUNDLE);
-
- var actions = [];
- var c_friend = this._coop.get(aFriendURN);
- if (c_friend) {
- var c_acct = this._coop.get(this.urn);
- for each (var i in actionNames) {
- actions.push({
- label: bundle.GetStringFromName("flock.youtube.actions." + i),
- class: i,
- spec: this.webDetective.getString("youtube", i, "")
- .replace("%accountid%", c_acct.accountId)
- .replace("%friendid%", c_friend.accountId)
- });
- }
- }
- return JSON.toString(actions);
- }
-
- youtubeAccount.prototype.getSharingAction =
- function youtubeAccount_getSharingAction(aFriendURN, aTransferable)
- {
- this._logger.info(".getSharingAction('" + aFriendURN + "')");
-
- var sharingAction = "";
- var c_friend = this._coop.get(aFriendURN);
- if (c_friend) {
- var flavors = ["text/x-flock-media",
- "text/x-moz-url",
- "text/unicode",
- "text/html"];
-
- var message = Cc[FLOCK_RDDS_CONTRACTID]
- .getService(Ci.flockIRichDNDService)
- .getMessageFromTransferable(aTransferable,
- flavors.length,
- flavors);
- if (!message.body) {
- return sharingAction;
- } else {
- var videoId = this.service.getVideoIDFromUrl(message.body);
- if (videoId) {
- sharingAction = this.webDetective.getString("youtube",
- "shareAction_sharevideo",
- "");
- } else {
- sharingAction = this.webDetective.getString("youtube",
- "shareAction_privatemessage",
- "");
- }
- }
- }
- this._logger.info(sharingAction);
- return sharingAction;
- }
-
- youtubeAccount.prototype.getProfileURLForFriend =
- function youtubeAccount_getProfileURLForFriend(aFriendURN)
- {
- this._logger.info(".getProfileURLForFriend('" + aFriendURN + "')");
-
- var url = "";
- var c_friend = this._coop.get(aFriendURN);
- if (c_friend) {
- url = this.webDetective.getString("youtube", "friendprofile", "")
- .replace("%accountid%", c_friend.accountId);
- }
-
- return url;
- }
-
- youtubeAccount.prototype.getPostLinkAction =
- function youtubeAccount_getPostLinkAction(aTransferable)
- {
- return "";
- }
- // END flockISocialWebServiceAccount interface
-
- // BEGIN flockIYoutubeAccount interface
- youtubeAccount.prototype.shareFlock =
- function youtubeAccount_shareFlock(aFriendURN)
- {
- this._logger.info(".shareFlock('" + aFriendURN + "')");
-
- var sbs = Cc["@mozilla.org/intl/stringbundle;1"]
- .getService(Ci.nsIStringBundleService);
- var bundle = sbs.createBundle(YOUTUBE_STRING_BUNDLE);
- var body = bundle.GetStringFromName("flock.youtube.friendShareFlock.message");
- var subj = bundle.GetStringFromName("flock.youtube.friendShareFlock.subject");
- this._composeMessage(aFriendURN, subj, body, false);
- }
-
- youtubeAccount.prototype.youtubePrivateMessage =
- function YoutubeAccount_youtubePrivateMessage(aFriendURN, aTransferable)
- {
- this._logger.info(".youtubePrivateMessage('" + aFriendURN + "')");
-
- var flavors = ["text/x-flock-media",
- "text/x-moz-url",
- "text/unicode",
- "text/html"];
-
- var message = Cc[FLOCK_RDDS_CONTRACTID]
- .getService(Ci.flockIRichDNDService)
- .getMessageFromTransferable(aTransferable,
- flavors.length,
- flavors);
- if (message.body) {
- this._composeMessage(aFriendURN, message.subject, message.body, true);
- }
- }
-
- youtubeAccount.prototype.youtubeShareVideo =
- function youtubeAccount_youtubeShareVideo(aFriendURN, aTransferable)
- {
- this._logger.info(".youtubeShareVideo('" + aFriendURN + "')");
-
- var flavors = ["text/x-flock-media",
- "text/x-moz-url",
- "text/unicode",
- "text/html"];
-
- var message = Cc[FLOCK_RDDS_CONTRACTID]
- .getService(Ci.flockIRichDNDService)
- .getMessageFromTransferable(aTransferable,
- flavors.length,
- flavors);
- if (message.body) {
- var inst = this;
- var share_url = inst.webDetective.getString("youtube",
- "shareIframeURL", "");
- var obs = Cc["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService);
- var videoId = this.service.getVideoIDFromUrl(message.body);
- var url = this.webDetective.getString("youtube", "youtubeShare_URL", "")
- .replace("%videoid%", videoId);
- var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
- .getService(Ci.nsIWindowMediator);
- var win = wm.getMostRecentWindow("navigator:browser");
- var dimen = inst.webDetective.getString("youtube",
- "shareAction_sharevideo_features",
- "");
- win.open(url, "Share", dimen);
- win = wm.getMostRecentWindow("navigator:browser");
- flockDocumentReadyObserver = {
- observe: function openShareVideo_FormFill (aSubject, aTopic, aData) {
- if (aData == share_url) {
- obs.removeObserver(this, "FlockDocumentReady");
- var contentWindow = win.gBrowser.docShell
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow);
-
- function insertContent(aDoc, aXpathquery, aAction, aMessage) {
- var formItems = aDoc.evaluate(aXpathquery, aDoc, null,
- Ci.nsIDOMXPathResult.ANY_TYPE, null);
- if (formItems) {
- var formItem = formItems.iterateNext();
- if (!formItem) {
- return;
- }
- switch (aAction) {
- case "click":
- formItem.click();
- break;
-
- case "username":
- if (formItem.hasAttribute("value")) {
- formItem.setAttribute("value", aMessage);
- }
- break;
-
- case "message":
- var textNode = doc.createTextNode(aMessage);
- formItem.appendChild(textNode);
- break;
-
- default:
- inst._logger.debug("no action associated with " + aAction);
- }
- }
- }
- var doc = contentWindow.document;
- // Insert Flock bread crumb
- var breadcrumb = Cc[FLOCK_RDDS_CONTRACTID]
- .getService(Ci.flockIRichDNDService)
- .getBreadcrumb("plain");
- if (breadcrumb) {
- var webDicName = "youtubeshareVideo_message";
- var xpathquery = inst.webDetective.getString("youtube",
- webDicName, "");
- insertContent(doc, xpathquery, "message", breadcrumb);
- }
-
- // Insert friend trying to save to into iframe
- webDicName = "youtubeshareVideo_IframeXPath";
- xpathquery = inst.webDetective.getString("youtube",
- webDicName, "");
- var formItems = doc.evaluate(xpathquery, doc, null,
- Ci.nsIDOMXPathResult.ANY_TYPE, null);
- if (formItems) {
- var iframe = formItems.iterateNext();
- if (iframe) {
- var c_friend = inst._coop.get(aFriendURN);
- webDicName = "youtubeshareVideo_friendCheckXPath";
- xpathquery = inst.webDetective.getString("youtube", webDicName, "")
- .replace("%friendname%", c_friend.name);
- insertContent(iframe.contentDocument, xpathquery, "click");
- }
- }
- }
- }
- };
- obs.addObserver(flockDocumentReadyObserver, 'FlockDocumentReady', false);
- }
- }
-
- youtubeAccount.prototype._composeMessage =
- function youtubeAccount__composeMessage(aFriendURN, aSubject, aBody, addBreadCrumb)
- {
- var body = aBody;
- var subject = aSubject;
- var c_friend = this._coop.get(aFriendURN);
- var url = this.webDetective.getString("youtube", "youtubeMessage_URL", "")
- .replace("%friendid%", c_friend.accountId);
- var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
- .getService(Ci.nsIWindowMediator);
- var win = wm.getMostRecentWindow("navigator:browser");
- if (win) {
- var browser = win.getBrowser();
- var newTab = browser.loadOneTab(url, null, null, null, false, false);
- var obs = Cc["@mozilla.org/observer-service;1"]
- .getService(Ci.nsIObserverService);
- var inst = this;
- var observer = {
- observe: function openSendMessageTabForFill_observer(aContent,
- aTopic,
- aContextUrl)
- {
- var contentWindow = newTab.linkedBrowser.docShell
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindow);
- function insertContent(aWebDicString, aMessage) {
- var xpathquery = inst.webDetective.getString("youtube", aWebDicString, "");
- var doc = contentWindow.document;
- var formItems = doc.evaluate(xpathquery, doc, null,
- Ci.nsIDOMXPathResult.ANY_TYPE, null);
- if (formItems) {
- var formItem = formItems.iterateNext();
- if (formItem.hasAttribute("value")) {
- formItem.setAttribute("value", aMessage);
- } else {
- var textNode = doc.createTextNode(aMessage);
- formItem.appendChild(textNode);
- inst._logger.info("aMessage " + aMessage);
- }
- }
- }
- if (contentWindow == aContent) {
- obs.removeObserver(this, "EndDocumentLoad");
- insertContent("youtubemessage_subjectXPath", subject);
- if (addBreadCrumb) {
- // Add breadcrumb to message body
- var breadcrumb = Cc[FLOCK_RDDS_CONTRACTID]
- .getService(Ci.flockIRichDNDService)
- .getBreadcrumb("plain");
- if (breadcrumb) {
- body += breadcrumb;
- }
- }
- insertContent("youtubemessage_bodyXPath", body);
- }
- }
- };
- obs.addObserver(observer, "EndDocumentLoad", false);
- }
- }
- // END flockIYoutubeAccount interface
-
- // ========== END youtubeAccount class ==========
-
-
-
- // ==============================================
- // ========== BEGIN XPCOM registration ==========
- // ==============================================
-
- function createModule(aParams) {
- return {
- registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
- aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
- aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
- aParams.contractID, aFileSpec,
- aLocation, aType );
- var catMgr = Cc["@mozilla.org/categorymanager;1"]
- .getService(Ci.nsICategoryManager);
- if (!aParams.categories) { aParams.categories = []; }
- for (var i = 0; i < aParams.categories.length; i++) {
- var cat = aParams.categories[i];
- catMgr.addCategoryEntry( cat.category, cat.entry,
- cat.value, true, true );
- }
- },
- getClassObject: function (aCompMgr, aCID, aIID) {
- if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
- if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
- return { // Factory
- createInstance: function (aOuter, aIID) {
- if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
- var comp = new aParams.componentClass();
- if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
- return comp.QueryInterface(aIID);
- }
- };
- },
- canUnload: function (aCompMgr) { return true; }
- };
- }
-
- // NS Module entrypoint
- function NSGetModule(aCompMgr, aFileSpec) {
- return createModule({
- componentClass: youtubeService,
- CID: YOUTUBE_CID,
- contractID: YOUTUBE_CONTRACTID,
- componentName: CATEGORY_COMPONENT_NAME,
- implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); },
- categories: [
- { category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: YOUTUBE_CONTRACTID },
- { category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: YOUTUBE_CONTRACTID },
- { category: "flockMediaProvider", entry: CATEGORY_ENTRY_NAME, value: YOUTUBE_CONTRACTID },
- { category: "flockRichContentHandler", entry: CATEGORY_ENTRY_NAME, value: YOUTUBE_CONTRACTID }
- ]
- });
- }
-
- // ========== END XPCOM registration ==========
-
-
-
- // HELPER STUFF
-
- function loadSubScript(spec)
- {
- var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Components.interfaces.mozIJSSubScriptLoader);
- var context = {};
- loader.loadSubScript(spec, context);
- return context;
- }
-
- function loadLibraryFromSpec(aSpec)
- {
- var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Components.interfaces.mozIJSSubScriptLoader);
- loader.loadSubScript(aSpec);
- }
-